package com.ydh.company.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


public class JwtUtil {

    /**
     * 过期时间一天，
     * TODO 正式运行时修改为15分钟
     */
    private static final long EXPIRE_TIME = 24 * 60 * 60 * 1000;
    /**
     * token私钥 (uuid，加密方式为HMAC256)
     */
    private static final String TOKEN_SECRET = "f26e587c28064d0e855e72c0a6a0e618";

    /**
     * JWT由三部分组成：header、payload、signature。
     *
     * header：头部包含了两部分，采用的签名算法和token 类型
     * {
     *   "alg": "HS256",
     *   "typ": "JWT"
     * }
     *
     * payload：是用于我们存放信息的
     *
     * 用户自定义的字段：
     * 用户 NAME ID 等信息放在这里(当然用户ID推荐加密后存放)，
     *
     * JWT标准定义的几个字段：
     * 常用的有 iss（签发者），iat（签发时间），
     * exp（过期时间），sub（面向的用户），aud（接收方）。
     *
     * {
     *   "name": "John Doe",
     *   "exp": 1516239022,
     * }
     *
     * signature：用header里描述的算法，和后台的秘钥，
     * 把header和payload的base64字符串拼接完以后，进行加密
     *
     * token =  header + payload + 秘钥（一串密码） 通过  signature 进行混合加密
     *
     */

    /**
     * 生成token签名
     *
     * @return 加密的token
     */
    public static String sign() {
        try {
//          过期时间
            Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
//            私钥及加密算法
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);

//          设置头部信息
            Map<String, Object> header = new HashMap<>(2);
            header.put("typ", "JWT");
            header.put("alg", "HS256");

            // 附带username，id信息，生成签名
            return JWT.create()
//                  添加头信息
                    .withHeader(header)
//                    添加JWT标准信息-有效期
                    .withExpiresAt(date)
//                    开始加密 需要传入秘钥
                    .sign(algorithm);
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }

    /**
     * 解码，解密token、验证token是否超时
     *
     * @param token 密钥
     * @return 0：解码，解密token成功，放行  1：解码，解密token失败，不放行
     */
    public static int verify(String token) {
        try {
//            解码，解密token
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            JWTVerifier verifier = JWT.require(algorithm).build();
            DecodedJWT jwt = verifier.verify(token);
//            最简单的办法，只要解码，解密token成功直接放行
            return 0;
        } catch (UnsupportedEncodingException e) {
            return 1;
        }
    }

    /**
     * 获得token中的信息无需secret解密也能获得
     *
     * @return token中包含的用户名
     */
    public static String getUsername(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("username").asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

    /**
     * 获取登陆用户密码
     *
     * @param token
     * @return
     */
    public static String getUserroleId(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("roleId").asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

}
